home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 31
/
Aminet 31 (1999)(Schatztruhe)[!][Jun 1999].iso
/
Aminet
/
dev
/
c
/
cflow.lha
/
cflow-2.0
/
prcc.c
< prev
next >
Wrap
C/C++ Source or Header
|
1999-02-20
|
28KB
|
1,158 lines
/* prcc.c: This file contains the parser for the calls command. */
/* This program is a modification of Steve Kirkendall's ctags(1) which
* is distributed as part of his vi-clone elvis. It is contributed
* to the public domain by Andrew Moore of Talke Studio. */
static char *id = "$Id: prcc.c,v 1.4 1995/02/16 05:35:57 leisner Exp $";
static char *version = "$Revision: 1.4 $";
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>
typedef enum { FALSE=0, TRUE=1 } BOOLEAN;
#ifndef PATH_MAX
#define PATH_MAX 1024
#endif
typedef struct ns { /* name structure */
struct ns *next;
char *name;
} name_t;
/* maximum identify length... */
#ifndef NAME_MAX
#define NAME_MAX 32
#endif
#define TAG_MAX (NAME_MAX * 2 + PATH_MAX + 20) /* maximum tag length */
#define TAG_STACKSIZE 20 /* tag stack size */
#include "prcc.prototypes.h"
/* The following boolean variables are set according to command line flags */
static int incl_vars; /* -v include variables */
static int gnu_keywords; /* -g deletes GNU keywords */
static int posix_keywords; /* -p deletes posix keywords */
static int ansi_keywords; /* -a deletes ansi keywords */
/* These are used for reading a source file. It keeps track of line numbers */
static char file_name[PATH_MAX]; /* name of the current file */
static FILE *file_fp; /* stream used for reading the file */
static long file_lnum; /* line number in the current file */
static int file_afternl; /* boolean: was previous character a newline? */
static int file_prevch; /* a single character that was ungotten */
static char *progname;
static char lex_name[NAME_MAX+1]; /* the name of a "NAME" token */
static void usage(void)
{
fprintf(stderr, "%s [-akgvp] [files]\n", progname);
fprintf(stderr, "\t-a\tdelete ansi keywords\n");
fprintf(stderr, "\t-g\tdelete gnu keywords\n");
fprintf(stderr, "\t-p\tdelete posix keywords\n");
fprintf(stderr, "\t-v\tinclude variables\n");
fprintf(stderr, "\t-k\tprint names to stdout and exit\n");
exit(2);
}
void main(int argc, char **argv)
{
extern int optind;
extern char *optarg;
int c;
progname = argv[0];
/* parse the option flags */
while (1) {
c = getopt(argc, argv, "pakgv");
if (c == -1)
break;
switch (c) {
case 'k':
show_all_lists();
exit(1);
case 'g':
gnu_keywords = TRUE;
break;
case 'a':
ansi_keywords = TRUE;
break;
case 'p':
posix_keywords = TRUE;
break;
case 'v':
incl_vars = TRUE;
break;
default:
usage();
}
}
argv += optind;
do {
/* can't open file */
if (!cpp_open(*argv ? *argv++ : "-")) {
break; /* least the error goes unnoticed */
}
/* initialize name lists */
per_file_init();
/* process file */
ctags();
/* free name lists */
per_file_cleanup();
} while (*argv);
/* flush tag stack */
maketag(0, 0);
exit(0);
/*NOTREACHED */
}
/* -------------------------------------------------------------------------- */
/* This is the parser. It locates tag candidates, and then decides
* whether to generate a tag for them. */
/* These are C tokens after which a parenthesis is valid
* which would otherwise be tagged as function names. The
* reserved words which are not listed are break, continue,
* default and goto. */
static char *reserved[] =
{
"extern",
"auto", "case", "char", "const", "do", "double", "else",
"entry", "enum", "extern", "float", "for",
"if", "int", "long", "register", "return", "short",
"signed", "sizeof", "static", "struct", "switch", "typedef",
"union", "unsigned", "void", "volatile", "while",
0
};
static char *gnu_reserved[] =
{
"asm", "__asm__",
"__attribute__",
"__complex__",
"__real__",
"__imag__",
"__const__",
"__extension__",
"inline", "__inline__",
"__label__",
"__signed__",
"typeof", "__typeof__",
"__volatile__",
0
};
/* this also includes bsd'isms...not really exact, but
* good enough
*/
static char *posix_reserved[] =
{
"access", "alarm", "brk", "chdir",
"chmod", "chown", "fchmod",
"close", "closedir",
"creat",
"ctermid", "cuserid",
"dup", "dup2",
"execl", "execle", "execlp", "execlpe",
"execv", "execve", "execvp", "execvpe",
"_exit",
"errno",
"fdopen",
"fstat",
"fork",
"getcwd", "getegid", "getenv", "geteuid", "getgid", "getgrent",
"getprgid", "getgrnam", "getlogin", "getpass", "getpgrp",
"getpid", "getppid", "getpwent", "getpwnam", "getpwuid", "getuid",
"ioctl",
"isatty",
"kill",
"link", "lseek", "mkdir", "mkfifo", "mknod",
"read",
"open",
"opendir", "pause", "pipe", "readdir",
"perror",
"popen", "pclose",
"rmdir", "rename", "unlink",
"sbrk", "setuid", "signal", "sleep", "stat",
"time", "times", "ttyname", "umask", "uname",
"unlink",
"ustat", "utime",
"sigaction",
"write",
0
};
static char *ansi_reserved[] =
{
"atexit",
"exit",
/* stdio function */
"fflush",
"fopen",
"fclose",
"fread", "fwrite",
"fprintf",
"fgets",
"fputs",
"fscanf",
"printf",
"putchar",
"putc", "fputc", "puts",
"scanf",
"signal",
"system",
"sscanf",
"sprintf",
"vfprintf",
"vprintf",
/* string functions */
"index", "rindex", "bcopy",
"strcat", "strncat", "strlen", "strcpy", "strncpy",
"strchr", "strrchr",
"strdup", "strcmp", "strncmp", "strncasecmp", "strcasecmp",
/* math functions */
/* memory functions */
"malloc", "realloc", "calloc", "free",
"memcpy", "memmove",
0
};
/* list of reserved words */
static name_t *keyword;
enum lex_tokens { /* token types */
DELETED,
BODY,
BODYEND,
LBRACKET,
RBRACKET,
ARGS,
ARGSEND,
COMMA,
SEMICOLON,
COLON,
KSTATIC,
KEXTERN,
KSTRUCT,
KTYPEDEF,
TYPESPEC,
NAME,
STRUREF,
ASSIGN,
OPERATOR
};
/* Basic types for initializing type specifier list */
static char *type[] =
{
"char", "double", "enum", "float", "int", "long", "short",
"signed", "struct", "union", "unsigned", "void",
0
};
/* A type specifer list prevents declarations such as: int (*func())();
* from being parsed as calls */
static name_t *type_specifier;
/* A functions-previously-defined list assures that functions are defined
* only once. */
static name_t *func_defined;
/* A functions/variables-previously-called list assures that calls are
* printed only once per function definition. */
static name_t *per_func_ref;
/* Three variables lists to track global/extern/local variable
* declarations. */
static name_t *variable;
static name_t *extern_var;
static name_t *per_func_var;
static int gotname; /* boolean: does lex_name contain a tag candidate? */
static int blockno; /* marks the extent of a scope */
static int listno; /* marks the extent of a parameter list */
static int func_seen; /* boolean: true if function is redefined */
/* This function parses a source file and prints function calls. */
static void ctags(void)
{
int initializer = FALSE; /* initialization list */
int prev; /* the previous token from the source file */
int token = SEMICOLON; /* the current token from the source file */
int scope = 0; /* normally 0, but could be KTYPEDEF or KSTATIC */
int scopeno = 0; /* block number upon entering a scope */
int structdeclr = FALSE; /* struct/union/enum declaration */
int structno = 0; /* block number upon entering struct */
int typedeclr = FALSE; /* type declaration */
/* reset */
gotname = FALSE;
/* parse until the end of the file */
while (prev = token, (token = lex_gettoken()) != EOF) {
/* scope keyword? */
if (token == KTYPEDEF || token == KSTATIC || token == KEXTERN) {
/* set scope */
scope = token;
scopeno = blockno;
gotname = FALSE;
continue;
}
/* type declaration */
if (token == KSTRUCT || token == TYPESPEC) {
typedeclr = TRUE;
gotname = FALSE;
continue;
}
/* (not STRUREF) NAME: NAME is tag? */
if (token == NAME && prev != STRUREF && prev != KSTRUCT) {
gotname = TRUE;
continue;
}
/* ASSIGN BODY: initilizer */
if (token == BODY && prev == ASSIGN) {
gotname = FALSE;
/* global */
if (blockno == 1) {
initializer = TRUE;
}
continue;
}
/* [NAME] BODY (no ARGS): struct declr [NAME is a struct tag] */
if (token == BODY && prev != ARGS) {
gotname =